/*******************************************************************************
 * Copyright 2011 Towee.net
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package net.towee.server.ftp;

import java.util.Arrays;

import javax.inject.Inject;

import net.towee.model.account.AccountData;
import net.towee.model.utils.Pair;
import net.towee.server.authentication.PasswordDigest;
import net.towee.server.persistence.AccountStore;
import net.towee.shared.exceptions.PersistenceException;

import org.apache.ftpserver.ftplet.Authentication;
import org.apache.ftpserver.ftplet.AuthenticationFailedException;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.User;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.usermanager.UsernamePasswordAuthentication;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.ConcurrentLoginPermission;
import org.apache.ftpserver.usermanager.impl.TransferRatePermission;
import org.eclipse.jetty.util.log.Log;

/**
 * This implementation of UserManager works with
 * users stored in AccountStore.
 * 
 * @author viiv.c58@gmail.com (Artem Artem'ev)
 */
public class FtpUserManager implements UserManager {
	private final AccountStore accountStore;
	
	@Inject
	public FtpUserManager(AccountStore accountStore){
		this.accountStore = accountStore;
	}
	
	@Override
	public User authenticate(Authentication tmp)
			throws AuthenticationFailedException {
		if(tmp instanceof UsernamePasswordAuthentication) {
			UsernamePasswordAuthentication auth = (UsernamePasswordAuthentication)tmp;
			
			// Try to get user
			try {
				AccountData acc = accountStore.getAccountByEmail( auth.getUsername() );
				
				// Verify user password
				Pair<byte[], byte[]> sd = acc.getSaltDigest();
				PasswordDigest digest = new PasswordDigest(sd.getFirst(), sd.getSecond());
				if( !digest.verify( auth.getPassword().toCharArray() ) )
					throw new AuthenticationFailedException();
				
				// Create user
				BaseUser user = new BaseUser();
				user.setEnabled(true);
				user.setName( acc.getId() );
				user.setPassword(null);
				user.setHomeDirectory("/");
				
				return user;
			} catch (PersistenceException e) {
				throw new AuthenticationFailedException();
			}
		}
		
		throw new AuthenticationFailedException();
	}

	@Override
	public void delete(String arg0) throws FtpException {
		Log.warn("Delete account not implemented");
	}

	@Override
	public boolean doesExist(String user) throws FtpException {
		try {
			accountStore.getAccountByEmail(user);
			return true;
		} catch (PersistenceException e) {
			return false;
		}
	}

	@Override
	public String getAdminName() throws FtpException {
		return null;
	}

	@Override
	public String[] getAllUserNames() throws FtpException {
		return null;
	}

	@Override
	public User getUserByName(String userName) throws FtpException {
		try {
			AccountData acc = accountStore.getAccountByEmail( userName, "_id" );
			System.out.println(userName);
			
			BaseUser user = new BaseUser();
			user.setEnabled(true);
			user.setName( acc.getId() );
			user.setPassword(null);
			user.setHomeDirectory("/");
			
			// Set authorities
			user.setAuthorities( Arrays.asList( (Authority)new ConcurrentLoginPermission(3, 3),
					(Authority)new TransferRatePermission(1, 1)));
			
			return user;
		} catch (PersistenceException e) {
			return null;
		}
	}

	@Override
	public boolean isAdmin(String arg0) throws FtpException {
		return false;
	}

	@Override
	public void save(User arg0) throws FtpException {
		Log.warn("Save account not implemented");
	}
}
